package com.bot.nft.chain.provider;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.bot.common.chainbo.ChainAccountInfo;
import com.bot.common.chainbo.TradingResultsInfo;
import com.bot.common.exception.CommonException;
import com.bot.dev.api.DevBlockChainApi;
import com.bot.nft.core.config.AvataUtils;
import com.bot.nft.core.config.BlockchainUtil;
import com.bot.nft.core.enums.chain.ChainOptEnum;
import com.bot.nft.core.util.ChainRequestUtil;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class DevBlockChainApiImpl implements DevBlockChainApi {


    /**
     * 创建链账户
     *
     * @return
     */
    @Override
    public ChainAccountInfo creatBlockChain() {
        UUID uuid = UUID.randomUUID();
        String path = ChainOptEnum.URI_CREATE_ACCOUNT.getValue();
        Map<String, Object> query = new HashMap<>();
        Map<String, Object> body = new HashMap<>();
        body.put("name", ChainOptEnum.BOT_NFT.getValue());
        body.put("operation_id", uuid);
        String result = ChainRequestUtil.post(path, query, body).body();
        Map map = JSON.parseObject(result, Map.class);
        Object data = map.get("data");
        ChainAccountInfo chainAccountInfo = BeanUtil.toBean(data, ChainAccountInfo.class);
        return chainAccountInfo;
    }

    /**
     * 创建NFT类别
     *
     * @param chainAccountInfo
     * @return
     */
    @Override
    public String creatNftClass(ChainAccountInfo chainAccountInfo) {
        String uriHash = SecureUtil.md5(chainAccountInfo.getUri());
        String uuid = UUID.randomUUID().toString();

        String path = ChainOptEnum.URI_CREATE_NFT_CLASS.getValue();
        Map<String, Object> query = new HashMap<>();
        Map<String, Object> body = new HashMap<>();
        //加入藏品名称
        body.put("name", chainAccountInfo.getName());
        body.put("symbol", BlockchainUtil.getAccount() + chainAccountInfo.getNftId());
        //加入藏品描述
        body.put("description", chainAccountInfo.getDescription());
        //加入藏品url
        body.put("uri", chainAccountInfo.getUri());
        //加入藏品加密后的url
        body.put("uri_hash", uriHash);
        //加入藏品data
        body.put("data", chainAccountInfo.getData());
        //加入藏品平台链上标识
        body.put("owner", BlockchainUtil.getAddress());
        //加入藏品uuid
        body.put("operation_id", uuid);
        //获取响应状态
        String status = String.valueOf(ChainRequestUtil.post(path, query, body).getStatus());
        //根据藏品名称查询藏品类别
        if (!status.equals(ChainOptEnum.SUCCESSFUL_CODE.getValue())) {
            throw new CommonException("网络异常");
        }
        return uuid;
    }

    /**
     * 发行NFT
     *
     * @param chainAccountInfo
     * @return 操作id
     */
    @Override
    public String publishNft(ChainAccountInfo chainAccountInfo) {
        //发行藏品
        String url = ChainOptEnum.URI_RELEASE_NFT.getValue();
        //获取API Secret
        String apiSecret = BlockchainUtil.getApiSecret();
        //获取藏品名称
        String name = chainAccountInfo.getName();
        //获取藏品uri
        String uri = chainAccountInfo.getUri();
        //获取链上标识
        String classId = chainAccountInfo.getClassId();
        //获取藏品类型
        Integer type = chainAccountInfo.getType();
        //获取发售时间
        Date saleTime = chainAccountInfo.getSaleTime();
        //获取接收者地址
        String recipient = chainAccountInfo.getNativeAddress();
        //path
        String path = url + classId;
        //获取操作ID
        String operationId = UUID.randomUUID().toString();
        System.out.println("operationId:" + operationId);
        //获取uriHash
        String uriHash = UUID.randomUUID().toString();
        System.out.println("uriHash:" + uriHash);
        Random random = new Random();
        int num = random.nextInt(1000);
        //获取当前时间戳
        long l = System.currentTimeMillis();
        System.out.println("X-Timestamp:" + l);

        String data = name + "," + saleTime + "," + type;
        name = name + "#" + num;
        Map<String, Object> query = new HashMap<>();
        Map<String, Object> body = new HashMap<>();
        body.put("name", name);
        body.put("uri", uri);
        body.put("uri_hash", uriHash);
        body.put("data", data);
        body.put("recipient", recipient);
        body.put("operation_id", operationId);
        String jsonStr = JSONUtil.toJsonStr(body);
        //获取SHA256API签名
        String signature = AvataUtils.signRequest(path, query, body, l, apiSecret);
        System.out.println(signature);

        HttpResponse post = ChainRequestUtil.post(path, query, body);
        String status = String.valueOf(post.getStatus());
        if (!status.equals(ChainOptEnum.SUCCESSFUL_CODE.getValue())) {
            throw new CommonException("网络异常");
        }
        return operationId;
    }

    /**
     * 转让NFT
     *
     * @param nftChainId   藏品链上标识
     * @param certChainId  藏品证书链上标识标识
     * @param ownerChainId 持有人链上标识
     * @param recChainId   接收人链上标识标识
     * @return 成功失败
     */
    @Override
    public String makeOverNft(String nftChainId, String certChainId, String ownerChainId, String recChainId) {

        //请求路径
        String path = ChainOptEnum.URI_TRANSFER_NFT.getValue() + nftChainId + "/" + ownerChainId + "/" + certChainId;
        //操作标识
        String operationId = UUID.randomUUID().toString();
        //Query 参数
        Map<String, Object> query = new HashMap<>();
        //Body 参数
        Map<String, Object> body = new HashMap<>();
        body.put("recipient", recChainId);
        body.put("operation_id", operationId);
        //链上转让
        HttpResponse post = ChainRequestUtil.post(path, query, body);
        String status = String.valueOf(post.getStatus());
        if (!status.equals(ChainOptEnum.SUCCESSFUL_CODE.getValue())) {
            throw new CommonException("网络异常");
        }
        return operationId;
    }

    /**
     * 销毁NFT
     *
     * @param classId  类别 ID
     * @param owner    NFT 持有者地址
     * @param nftIdDev NFT ID
     * @return
     */
    @Override
    public String disNft(String classId, String owner, String nftIdDev) {
        //路径
        String path = ChainOptEnum.URI_DESTROYED_NFT.getValue() + classId + "/" + owner + "/" + nftIdDev;
        //Query 参数
        Map<String, Object> query = new HashMap<>();
        //Body 参数
        Map<String, Object> body = new HashMap<>();
        //生成UUID
        String uuid = UUID.randomUUID().toString();
        body.put("operation_id", uuid);
        HttpResponse delete = ChainRequestUtil.delete(path, query, body);
        String status = String.valueOf(delete.getStatus());
        if (!status.equals(ChainOptEnum.SUCCESSFUL_CODE.getValue())) {
            throw new CommonException("网络异常");
        }
        return uuid;
    }

    /**
     * 查询交易记录
     *
     * @param operationId 操作 Id
     * @return
     */
    @Override
    public TradingResultsInfo queryTranRecords(String operationId) {
        //路径
        String path = ChainOptEnum.URI_QUERY_OPERATION_RESULTS.getValue() + operationId;
        //Query 参数
        Map<String, Object> query = new HashMap<>();
        //Body 参数
        Map<String, Object> body = new HashMap<>();
        HttpResponse httpResponse = ChainRequestUtil.get(path, query, body);
        String status = String.valueOf(httpResponse.getStatus());
        TradingResultsInfo tradingResults = null;
        if (status.equals(ChainOptEnum.SUCCESSFUL_CODE.getValue())) {
            tradingResults = TradingResultsInfo.fromJson(httpResponse.body());
        }
        return tradingResults;
    }
}